package com.gitee.yannzh.rune.support.crud.controller;

import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
import com.gitee.yannzh.rune.core.base.controller.BaseController;
import com.gitee.yannzh.rune.core.base.pagination.PageResult;
import com.gitee.yannzh.rune.core.base.pojo.Param;
import com.gitee.yannzh.rune.core.base.vo.Result;
import com.gitee.yannzh.rune.core.util.ValidateGroup;
import com.gitee.yannzh.rune.core.util.ValidationUtils;
import com.gitee.yannzh.rune.extension.mp.query.BaseQuery;
import com.gitee.yannzh.rune.support.crud.CrudHelper;
import com.gitee.yannzh.rune.support.crud.WebUtil;
import com.gitee.yannzh.rune.support.crud.base.IDefaultService;
import com.gitee.yannzh.rune.support.crud.constant.Api;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.validation.groups.Default;
import java.io.Serializable;
import java.util.List;
import java.util.function.Supplier;

@SuppressWarnings("unchecked")
public abstract class CRUDController<T, K extends Serializable> extends BaseController {

    @Autowired
    protected HttpServletRequest request;

    /**
     * 模型类型
     */
    protected Class<T> modelClass = currentModelClass();

    @Setter
    protected Class<? extends Param> defaultFormBeanClass;

    @Setter
    protected Class<? extends BaseQuery> queryFormBeanClass;

    @Setter
    protected Class<? extends Param> saveFormBeanClass;

    @Setter
    protected Class<? extends Param> updateFormBeanClass;

    public CRUDController(Class<? extends Param> defaultFormBeanClass) {
        this.defaultFormBeanClass = defaultFormBeanClass;
        this.queryFormBeanClass = (Class<? extends BaseQuery>) defaultFormBeanClass;
        this.saveFormBeanClass = defaultFormBeanClass;
        this.updateFormBeanClass = defaultFormBeanClass;
    }

    public <P extends BaseQuery> Class<P> getQueryFormBeanClass() {
        return (Class<P>) queryFormBeanClass;
    }

    public <P extends Param> Class<P> getSaveFormBeanClass() {
        return (Class<P>) saveFormBeanClass;
    }

    public <P extends Param> Class<P> getUpdateFormBeanClass() {
        return (Class<P>) updateFormBeanClass;
    }


    public <P extends Param> Class<P> getDefaultFormBeanClass() {
        return (Class<P>) defaultFormBeanClass;
    }

    private Class<T> currentModelClass() {
        return (Class<T>) ReflectionKit.getSuperClassGenericType(this.getClass(), CRUDController.class, 0);
    }

    public IDefaultService<T, ?> getService() {
        return CrudHelper.getCrudService(modelClass);
    }


    private <P extends Param> P getParams(Supplier<Class<P>> supplier, Class<?>... groups) {
        P param;
        try {
            param = (P) WebUtil.bindRequestParameter(request, supplier.get());
            ValidationUtils.validate(param, groups);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return param;
    }


    /**
     * 根据id查询
     *
     * @param id
     * @return
     */
    @RequestMapping()
    public Result<?> getById(K id) {
        return success(getService().getByKey(id));
    }

    /**
     * 分页查询
     *
     * @return
     */
    @RequestMapping(Api.PAGE)
    public <P extends BaseQuery> Result<PageResult<?>> page() {
        P params = getParams(this::getQueryFormBeanClass, new Class<?>[]{ValidateGroup.Query.class, Default.class});
        return success(getService().pageList(params));
    }

    @RequestMapping(Api.LIST)
    public <P extends BaseQuery> Result<List<?>> list() {
        P params = getParams(this::getQueryFormBeanClass, new Class<?>[]{ValidateGroup.Query.class, Default.class});
        return success(getService().find(params));
    }

    /**
     * 新增
     *
     * @param form
     * @return
     */
    @RequestMapping(Api.SAVE)
    public <P extends Param> Result<K> save() {
        P params = getParams(this::getSaveFormBeanClass, new Class<?>[]{ValidateGroup.Save.class, Default.class});
        return success((K) getService().save(params));
    }

    /**
     * 编辑
     *
     * @param form
     * @return
     */
    @RequestMapping(Api.UPDATE)
    public <P extends Param> Result<Void> update() {
        P params = getParams(this::getUpdateFormBeanClass, new Class<?>[]{ValidateGroup.Update.class, Default.class});
        getService().updateById(params);
        return success();
    }

    /**
     * 根据主键集合删除
     *
     * @param id
     * @return
     */
    @RequestMapping(Api.DELETE)
    public Result<Void> deleteById(K id) {
        getService().removeByKey(id);
        return success();
    }


    /**
     * 根据主键集合批量删除
     *
     * @param ids
     * @return
     */
//    @RequestMapping(Api.BATCH_DELETE)
//    public Result<Boolean> deleteByIds(@RequestParam("ids") List<K> ids) {
//        return success(getService().removeBatchByIds(ids));
//    }


    /**
     * excel通用导出功能
     *
     * @param query
     */
    protected <Q extends BaseQuery> void exportExcel(Q query) {
        getService().exportExcel(query, "exportExcel");
    }


    /**
     * excel导入
     *
     * @param file
     */
    protected Result<Void> importExcel(MultipartFile file) {
        getService().importExcel(file);
        return success();
    }


}
